package com.njupt.sellsec.controller;

import com.njupt.sellsec.access.AccessLimit;
import com.njupt.sellsec.domain.*;
import com.njupt.sellsec.exception.SellerAuthorizeException;
import com.njupt.sellsec.handler.UserContext;
import com.njupt.sellsec.rabbitmq.MQSender;
import com.njupt.sellsec.redis.*;
import com.njupt.sellsec.result.CodeMsg;
import com.njupt.sellsec.result.Result;
import com.njupt.sellsec.service.GoodsService;
import com.njupt.sellsec.service.Impl.SellUserServiceImpl;
import com.njupt.sellsec.service.OrderService;
import com.njupt.sellsec.service.SecSellService;
import com.njupt.sellsec.service.SellUserService;
import com.njupt.sellsec.util.MD5Util;
import com.njupt.sellsec.util.UUIDUtil;
import com.njupt.sellsec.vo.GoodsFormVO;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;

/**
 * @Author: XJL
 * @Description:
 * @Date: Create in 16:55 2018/7/29
 * @Modified By:
 **/
@Controller
@RequestMapping("/sell")
public class SecSellController implements InitializingBean{
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private SellUserService sellUserService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private SecSellService secSellService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private MQSender mqSender;

    private HashMap<Long,Boolean> localOverMap = new HashMap<Long,Boolean>();

    /**
     * 该方法会在该bean属性初始化之后执行
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {

        List<GoodsFormVO> goodsFormVOList = goodsService.getGoodsVOListById();
        if (goodsFormVOList==null){
            return;
        }else {
            for (GoodsFormVO goods:goodsFormVOList){

                redisService.set(GoodsKey.getSecSellGoodsStock,""+goods.getId(),goods.getStockCount());
                localOverMap.put(goods.getId(),false);
            }
        }


    }

    /**
     * 重设缓存数据
     * @param model
     * @return
     */
    @ResponseBody
    @RequestMapping("/reset")
    public Result<Boolean> reset(Model model){
        List<GoodsFormVO> goodsFormVOList = goodsService.getGoodsVOListById();
        for (GoodsFormVO goods: goodsFormVOList){
            goods.setStockCount(15);
            redisService.set(GoodsKey.getSecSellGoodsStock,""+goods.getId(),15);
            localOverMap.put(goods.getId(),false);
        }
        redisService.delete(OrderKey.getSecOrderByUidGid);
        redisService.delete(SecSellKey.isGoodsOver);
        secSellService.reset(goodsFormVOList);
        return Result.success(true);
    }

    /**
     * 执行秒杀
     * @param model
     * @param response
     * @param cookieValue
     * @param paramToken
     * @param goodsId
     * @param path
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/{path}/do_secsell",method = RequestMethod.POST)
    @ResponseBody
    public Result<Integer> secSell(Model model,
                          HttpServletResponse response,
                          @CookieValue(value = SellUserServiceImpl.COOKIE_NAME_TOKEN,required = false)String cookieValue,
                          @RequestParam(value = SellUserServiceImpl.COOKIE_NAME_TOKEN,required = false)String paramToken,
                          @RequestParam("goodsId")long goodsId,
                                   @PathVariable("path")String path) throws IOException {
        if (!StringUtils.isEmpty(paramToken)){

             paramToken = paramToken.replace(",","");
        }
        if (StringUtils.isEmpty(cookieValue)&& StringUtils.isEmpty(paramToken)){

            response.sendRedirect("/login/do_login");
            return null;
        }
        String token = StringUtils.isEmpty(paramToken)?cookieValue:paramToken;
        SellUser user = sellUserService.findUserByToken(response,token);
        model.addAttribute("user",user);

        boolean result = secSellService.check(path,user,goodsId);
        if (!result){
            return Result.error(CodeMsg.REQUEST_ILLEAGER);
        }

        //优化：当并发较高时，如果存储已经小于零了，剩下的线程就无需继续进行了
        boolean over = localOverMap.get(goodsId);
        if (over){
            return Result.error(CodeMsg.SEC_SELL_OVER);
        }


        //判断是否已经获得商品，从缓存中获取订单信息.
        SecOrder secOrder = orderService.getSecOrderByUserIdAndGoodsId(user.getId(),goodsId);
        if (secOrder!=null){
            model.addAttribute("errmsg",CodeMsg.REPEATE_SECSELL.getMsg());
            //response.sendRedirect("/sell/errorPage");
            // return null;
            return Result.error(CodeMsg.REPEATE_SECSELL);
        }



        //判断库存
        long stock = redisService.derc(GoodsKey.getSecSellGoodsStock,""+goodsId);
        if (stock<0){
            localOverMap.put(goodsId,true);
            return Result.error(CodeMsg.SEC_SELL_OVER);
        }


        //入队，利用消息对象排队下单
        SecSellMessage message = new SecSellMessage();
        message.setGoodsId(goodsId);
        message.setUser(user);
        mqSender.sendSecSellMessage(message);

       /* GoodsFormVO goodsFormVO = goodsService.getGoodInfoById(goodsId);

        if (goodsFormVO==null||goodsFormVO.getStockCount()<=0){
            //model.addAttribute("errmsg", CodeMsg.SEC_SELL_OVER.getMsg());
           // response.sendRedirect("/sell/errorPage");
            return Result.error(CodeMsg.SEC_SELL_OVER.getMsg());
        }
        //判断是否已经获得商品
        SecOrder secOrder = orderService.getSecOrderByUserIdAndGoodsId(user.getId(),goodsId);
        if (secOrder!=null){
            model.addAttribute("errmsg",CodeMsg.REPEATE_SECSELL.getMsg());
            //response.sendRedirect("/sell/errorPage");
           // return null;
            return Result.error(CodeMsg.REPEATE_SECSELL);
        }

        //减库存 ，下订单 ， 保存订单
        OrderInfo orderInfo = secSellService.secSell(user,goodsFormVO);
        model.addAttribute("orderInfo",orderInfo);
        model.addAttribute("goods",goodsFormVO);
        return Result.success(orderInfo);*/
        return Result.success(0);
    }


    /**
     * 获取秒杀结果
     * @param model
     * @param response
     * @param cookieValue
     * @param paramToken
     * @param goodsId
     * @return
     */
    @ResponseBody
    @GetMapping("/result")
    public Result<Long> secSellResult(Model model,
                                  HttpServletResponse response,
                                  @CookieValue(value = SellUserServiceImpl.COOKIE_NAME_TOKEN,required = false)String cookieValue,
                                  @RequestParam(value = SellUserServiceImpl.COOKIE_NAME_TOKEN,required = false)String paramToken,
                                  @RequestParam("goodsId")long goodsId){
        if (!StringUtils.isEmpty(paramToken)){

            paramToken = paramToken.replace(",","");
        }
        if (StringUtils.isEmpty(cookieValue)&& StringUtils.isEmpty(paramToken)){

            Result.error(CodeMsg.SESSION_ERROR);
        }
        String token = StringUtils.isEmpty(paramToken)?cookieValue:paramToken;
        SellUser user = sellUserService.findUserByToken(response,token);
        model.addAttribute("user",user);

        long result = secSellService.getSecSellResult(user.getId(),goodsId);
        System.out.println("+++++++++++++++++++++++++++++++++++"+result);
        return Result.success(result);
    }

    /**
     * 获取请求路径，并验证验证码结果
     * @param response
     * @param goodsId
     * @param model
     * @return
     */
    @AccessLimit(seconds = 5,maxCount = 5,needLogin = true)
    @GetMapping("/path")
    @ResponseBody
    public Result<String> getPath( HttpServletResponse response,
                                   HttpServletRequest request,
                                  /* @CookieValue(value = SellUserServiceImpl.COOKIE_NAME_TOKEN,required = false)String cookieValue,
                                   @RequestParam(value = SellUserServiceImpl.COOKIE_NAME_TOKEN,required = false)String paramToken,*/
                                   @RequestParam("goodsId")long goodsId,
                                   Model model,
                                   @RequestParam(value = "verifyCode",defaultValue = "0")int verifyCode){
        /*if (!StringUtils.isEmpty(paramToken)){

            paramToken = paramToken.replace(",","");
        }
        if (StringUtils.isEmpty(cookieValue)&& StringUtils.isEmpty(paramToken)){

            Result.error(CodeMsg.SESSION_ERROR);
        }
        String token = StringUtils.isEmpty(paramToken)?cookieValue:paramToken;*/
        SellUser user = UserContext.getUser();
      //  SellUser user = sellUserService.findUserByToken(response,token);
        if (user==null){
            throw new SellerAuthorizeException();
        }
        model.addAttribute("user",user);
        /*//接口限流5秒5次
        String uri = request.getRequestURI();
        String key = uri+"_"+user.getId();
        Integer count = redisService.get(AccseeKey.AccessController,key,Integer.class);
        if (count==null){
            redisService.set(AccseeKey.AccessController,key,1);
        }else if (count<5){
            redisService.incr(AccseeKey.AccessController,key);
        }else {
            return Result.error(CodeMsg.QEQUEST_LIMITED_REPEAUED);
        }*/


        boolean resutl = secSellService.checkVerifyCode(user,goodsId,verifyCode);
        if (!resutl){
            return Result.error(CodeMsg.REQUEST_ILLEAGER);
        }
        String path = MD5Util.md5(UUIDUtil.genUUID());
        redisService.set(SecSellKey.getSecSellPath,""+user.getId()+""+goodsId,path);
        return Result.success(path);
    }

    /**
     * 生成图片验证码
     * @param response
     * @param cookieValue
     * @param paramToken
     * @param goodsId
     * @return
     */
    @RequestMapping("/verifyCode")
    @ResponseBody
    public Result<String> getVerifyCode( HttpServletResponse response,
                                         @CookieValue(value = SellUserServiceImpl.COOKIE_NAME_TOKEN,required = false)String cookieValue,
                                         @RequestParam(value = SellUserServiceImpl.COOKIE_NAME_TOKEN,required = false)String paramToken,
                                         @RequestParam("goodsId")long goodsId){
            if (!StringUtils.isEmpty(paramToken)){

                paramToken = paramToken.replace(",","");
            }
            if (StringUtils.isEmpty(cookieValue)&& StringUtils.isEmpty(paramToken)){


                throw new SellerAuthorizeException();
            }
            String token = StringUtils.isEmpty(paramToken)?cookieValue:paramToken;
            SellUser user = sellUserService.findUserByToken(response,token);
            if (user==null){
                throw new SellerAuthorizeException();
            }
        BufferedImage image = secSellService.createVerifyCode(user,goodsId);
            try {
                OutputStream outputStream = response.getOutputStream();
                ImageIO.write(image,"JPEG",outputStream);
                outputStream.flush();
                outputStream.close();
                return null;
            }catch (Exception e){
                e.printStackTrace();
                return Result.error(CodeMsg.SECSELL_FAILRE);

            }
    }




}
